// *************************************************************************************************
//
// MK3D Engine
// --------------------------------------
// Copyright (C) 2007-2011 Zeb (mailto: zebbey@gmail.com)
//
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// *************************************************************************************************

#ifndef __H_MK_PARTICLE_EMITTER__
#define __H_MK_PARTICLE_EMITTER__

#include "mk_particle_common.h"
#include "mk_transformation.h"
#include "mk_particle_emitter_modifier.h"
#include "mk_particle_modifier.h"

namespace MK3DE
{
	class MK3DE_API CParticleEmitter : public CTransformation
	{
	private:
		// Emit count per second.
		float CountMin, CountMax;

		// Emit scatter angle.
		float ScatterMin, ScatterMax;

		// Init particle rotation angle.
		float RotationMin, RotationMax;

		// Init particle life.
		DWORD LifeMin, LifeMax;

		// Init particle speed.
		float SpeedMin, SpeedMax;

		// Init particle color.
		DWORD Color;

		// Init particle size.
		D3DXVECTOR2 ParticleSizeMin, ParticleSizeMax;

		// Whether the width is the same as height.
		BOOL SameWidthHeight;

		// Texture frame index.
		DWORD TextureFrame;

		// Render blend mode.
		PARTICLE_RENDER_BLEND_MODE ParticleBlendMode;

		// Shape type.
		PARTICLE_EMITTER_SHAPE_TYPE ShapeType;

		// Shape parameters. Different emitter shape with different meaning.
		float ShapeParam1;
		float ShapeParam2;
		float ShapeParam3;

		// Particle type.
		PARTICLE_TYPE ParticleType;

	public:
		DEF_SET_GET(float, CountMin);
		DEF_SET_GET(float, CountMax);

		DEF_SET_GET(float, ScatterMin);
		DEF_SET_GET(float, ScatterMax);

		DEF_SET_GET(float, RotationMin);
		DEF_SET_GET(float, RotationMax);

		DEF_SET_GET(DWORD, LifeMin);
		DEF_SET_GET(DWORD, LifeMax);

		DEF_SET_GET(float, SpeedMin);
		DEF_SET_GET(float, SpeedMax);

		DEF_SET_GET(DWORD, Color);

		DEF_SET_GET(D3DXVECTOR2, ParticleSizeMin);
		DEF_SET_GET(D3DXVECTOR2, ParticleSizeMax);

		DEF_SET_GET(BOOL, SameWidthHeight);

		DEF_SET_GET(DWORD, TextureFrame);

		DEF_SET_GET(PARTICLE_RENDER_BLEND_MODE, ParticleBlendMode);

		DEF_SET_GET(PARTICLE_EMITTER_SHAPE_TYPE, ShapeType);

		DEF_SET_GET(float, ShapeParam1);
		DEF_SET_GET(float, ShapeParam2);
		DEF_SET_GET(float, ShapeParam3);

		DEF_SET_GET(PARTICLE_TYPE, ParticleType);

	public:
		CParticleEmitter();
		~CParticleEmitter();

		BOOL AddEmitterModifier(/* out */ CParticleEmitterModifier*& pModifier, PARTICLE_EMITTER_MODIFIER_TYPE type);
		DWORD GetEmitterModifierCount() { return (DWORD)_vecEmitterModifier.size(); }
		CParticleEmitterModifier* GetEmitterModifier(DWORD idx);
		BOOL RemoveEmitterModifier(CParticleEmitterModifier* pModifier);

		BOOL AddParticleModifier(/* out */ CParticleModifier*& pModifier, PARTICLE_MODIFIER_TYPE type);
		DWORD GetParticleModifierCount() { return (DWORD)_vecParticleModifier.size(); }
		CParticleModifier* GetParticleModifier(DWORD idx);
		BOOL RemoveParticleModifier(CParticleModifier* pModifier);

		BOOL Update(DWORD dt, D3DXMATRIX& mat);

		DWORD GetParticleCount() { return (DWORD)_vecParticleIdx.size(); }

		void FillVertexBuffer(DWORD textureCutting);

	private:
		BOOL __EmitParticle(DWORD dt, D3DXMATRIX& mat);
		BOOL __ApplyEmitterModifier(DWORD dt);
		BOOL __UpdateParticle(DWORD dt);

		void __GetDirection(D3DXMATRIX& mat, float speed, D3DXVECTOR3& velocity);
		void __GetPosition(D3DXMATRIX& mat, D3DXVECTOR3& pos);

		void __Clean();

	private:
		std::vector<CParticleEmitterModifier*> _vecEmitterModifier;
		std::vector<CParticleModifier*> _vecParticleModifier;

		std::vector<DWORD> _vecParticleIdx;
		D3DXVECTOR3 _lastEmitPos;
		DWORD _remainEmitTime;

	};
};

#endif // __H_MK_PARTICLE_EMITTER__